#include <graphics/Viewport.h>

namespace ne
{
    Viewport::Viewport(Camera *camera)
        : mCamera(camera),
          mPosition(Vector2::ZERO),
          mWidth(1280),
          mHeight(720)
    {
        resize(mWidth, mHeight);
    }

    void Viewport::setCamera(Camera *camera)
    {
        mCamera = camera;
        resize(mWidth, mHeight);
    }

    Camera* Viewport::getCamera() const
    {
        return mCamera;
    }

    void Viewport::setPosition(const real x, const real y)
    {
        mPosition.x = x;
        mPosition.y = y;
    }

    void Viewport::setPosition(const Vector2 &v)
    {
        mPosition = v;
    }

    Vector2 Viewport::getPosition() const
    {
        return mPosition;
    }

    void Viewport::resize(const uint32_t width, const uint32_t height)
    {
        mWidth = width;
        mHeight = height;
        if (mCamera)
        {
            mCamera->setAspectRatio((real)width / height);
            mCamera->setOrthoWindowHeight((real)height);
        }
    }

    void Viewport::setWidth(const uint32_t width)
    {
        resize(width, mHeight);
    }

    uint32_t Viewport::getWidth() const
    {
        return mWidth;
    }

    void Viewport::setHeight(const uint32_t height)
    {
        resize(mWidth, height);
    }

    uint32_t Viewport::getHeight() const
    {
        return mHeight;
    }

    Ray Viewport::getScreenToWorldRay(const real x, const real y) const
    {
        Ray resRay;
        getScreenToWorldRay(x, y, resRay);
        return resRay;
    }

    void Viewport::getScreenToWorldRay(const real x, const real y, Ray &outRay) const
    {
        Vector2 v = getScreenToViewport(x, y);
        if (mCamera)
        {
            mCamera->getViewportToWorldRay(v.x, v.y, outRay);
        }
    }

    Ray Viewport::getScreenToCameraRay(const real x, const real y) const
    {
        Ray resRay;
        getScreenToCameraRay(x, y, resRay);
        return resRay;
    }

    void Viewport::getScreenToCameraRay(const real x, const real y, Ray &outRay) const
    {
        Vector2 v = getScreenToViewport(x, y);
        if (mCamera)
        {
            mCamera->getViewportToCameraRay(v.x, v.y, outRay);
        }
    }

    Vector2 Viewport::getScreenToViewport(const real x, const real y) const
    {
        Vector2 v;
        v.x = 2.0f * (x - mPosition.x) / mWidth - 1.0f;
        v.y = 1.0f - 2.0f * (y - mPosition.y) / mHeight;
        return v;
    }

    Viewport::~Viewport()
    {
    }
}
